Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store history in XDG data directory #253

Merged
merged 2 commits into from
Nov 4, 2021
Merged

Store history in XDG data directory #253

merged 2 commits into from
Nov 4, 2021

Conversation

xsebek
Copy link
Member

@xsebek xsebek commented Oct 21, 2021

  • fixes Store REPL history file in $XDG_DATA_HOME #136
  • changes the history file format to simple text line per REPLEntry
  • refactors out a REPLHistory type and its pure functions
    • adds tests for REPL logic (move to different previous entry,...)

@xsebek
Copy link
Member Author

xsebek commented Oct 21, 2021

The new history file path is:

echo "${XDG_DATA_HOME:-$HOME/.local/share}/swarm/history"

The quick and easy way to migrate old history using ghci:

data R = REPLEntry Bool String deriving Read
new_history = "<output of shell command above>"
readFile ".swarm_history" >>= pure . unlines . map (\(REPLEntry _ t) -> t) . read >>= writeFile new_history

@xsebek
Copy link
Member Author

xsebek commented Oct 21, 2021

Weird, I re-run the failing tests and have no idea what their problem is 😕 Maybe it will go away once rebased on main.
Oh, now I see #252 it makes sense 😄

@xsebek
Copy link
Member Author

xsebek commented Oct 21, 2021

I am unhapy with the current REPLEntry Bool Bool situation - I am considering:

  • splitting it into a separate type - data REPLHistItem = REPLIn REPLEntry | REPLOut, with lenses on REPLEntry
    • this would make it easier to add other properties
  • wrapping history, using some other container and having the neighbor logic in some function
    • I guess we could get by with just an index to start of loaded history and avoid Bools altogether

I could also do it as separate PR/Issue, but the first option is easy enough to do here.
What do you think @byorgey, @Alexander-Block? 🙂

Copy link
Member

@byorgey byorgey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks good to me. I agree REPLEntry Bool Bool is not great (to be clear, it was my idea, I'm not blaming @Alexander-Block =). I don't have a strong opinion on how we should fix it, either of the things you proposed would be an improvement.

@Alexander-Block
Copy link
Collaborator

I also agree that REPLEntry Bool Bool is far from optimal; upon reflection it mainly bothers me that the semantics of each Bool is not immediately obvious without reading the haddock comment for REPLHistItem. Apart from that I think that marking duplicates with an attribute is not a bad solution. This would be solved by your first proposed fix.

Do you see concrete advantages of your second proposal compared to the first one, @xsebek? If not, I slightly prefer the first one for its simplicity. I guess it should not be too hard to refactor to the second proposal later if it turns out to be a better solution.

However, this is also not a particularly strong opinion.

@xsebek
Copy link
Member Author

xsebek commented Oct 26, 2021

@Alexander-Block I thought about it and I think wrapping Seq is the right way ™️.

We are indexing a lot into history and Seq has some nice functions to find first index matching predicate from both directions, so that makes it superior in my eyes. There is some added complexity in adding new function names to remember but on the other hand Seq could be more appealing to imperative programmers that like random access.

I somehow managed to change it and get it to work again (off by one errors are the worst) but it could definitely be refactored further. I originally hoped to have all functions taking Seq REPLHistItem in Model.hs, but maybe it is not worth the trouble.

EDIT: just to clarify, with sequence I abandoned stack-like indexing so the historically first entry has index 0 and instead of -1 I use replLength for index of current buffer. I first tried keeping the old indices, but it did not play nicely with findIndexR.

@Alexander-Block
Copy link
Collaborator

Thank you for this thorough explanation. I agree with your arguments both for using Seq for the REPL history as well as wrapping it.

However, I also agree that this implementation could benefit from further refactoring. I find it a bit worrying to expose details of the inner storage outside Model.hs because it partially defeats the advantages of wrapping the REPL history by making clients dependent on an implementation detail. If we furthermore concentrate the logic for manipulating and accessing the REPL history in Model.hs we get the additional benefit of improving testability. Since you already mention that you had to deal with off-by-one errors, I think that it would be a good idea to add a suite of unit tests to make sure that the new implementation of the REPL history conforms (and continues to conform) to our expectations.

I would be happy to go through your code changes an do a more detailled review; I did not find the time to do that yesterday (which is why I write this vague comment), but I think that I will find time at some point today (from the perspective of the CEST time zone). Also I would be happy to propose unit tests as it will help me to better understand your code changes.

Copy link
Collaborator

@Alexander-Block Alexander-Block left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like the approach of having a REPLHistory type for a complete REPL history that is a wrapper around Seq.

However, I think that the idea of a wrapper could and should be taken further than is the case in the current implementation. The three lenses replSeq, replStart and replIndex completely reveal (and allow clients to manipulate) the inner structure of ReplHistory. I propose not to export them, but rather add a few additional functions to Model.hs to manipulate and access information from a REPLHistory. As I said earlier this will make it easier to unit test the behaviour connected with REPLHistory.

Apart from this I unfortunately found an error in drawREPL that should be corrected before merging this pull request.

@xsebek
Copy link
Member Author

xsebek commented Oct 28, 2021

Thanks for your detailed review @Alexander-Block, I am working through it and fixing bugs! 🐛🔨

@xsebek
Copy link
Member Author

xsebek commented Oct 28, 2021

For fun I also added a debugging line to show the index:

┌──────────────── string ──┐
 > (\x. "a") 1            
 56                       
└──────────────────────────┘

It is triggered by this line in drawREPL:

debugging = False -- Turn ON to get extra line with history index
inputLines = 1 + fromEnum debugging

Could be useful for #134. 🙂

@xsebek
Copy link
Member Author

xsebek commented Oct 28, 2021

I'm pretty happy with the result and I even added some unit tests so hopefully it works now. 😄

Could you please check it out and see if I did not miss anything, @Alexander-Block and @byorgey?

@Alexander-Block
Copy link
Collaborator

I noticed that the status of my review was still "requesting changes"; the reason for this status was the bug I noticed and which has since been fixed. There are still unresolved conversations, but these contain only comments which may or may not lead to changes in this PR and should probably not prevent a merge.

@byorgey
Copy link
Member

byorgey commented Nov 2, 2021

I think it looks good too, though I seem to recall @xsebek wanting to add some tests first? Or am I getting it confused with something else?

@Alexander-Block
Copy link
Collaborator

@xsebek has added unit tests (cf testModel in Unit.hs). They look fine to me, although I didn't explicitly commented on them.

- use Seq as inner storage
- skip same entries using predicate
- store index of first input that is not saved
@xsebek
Copy link
Member Author

xsebek commented Nov 4, 2021

@byorgey You might be thinking about #270, where I would indeed like to write some tests first 🙂

@Alexander-Block sorry for the delay, I actually had the changes you proposed implemented for almost a week now, just did not get around to test and push them 😉

@xsebek xsebek added the merge me Trigger the merge process of the Pull request. label Nov 4, 2021
@mergify mergify bot merged commit 05dad31 into main Nov 4, 2021
@mergify mergify bot deleted the xdg-history branch November 4, 2021 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merge me Trigger the merge process of the Pull request.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Store REPL history file in $XDG_DATA_HOME
3 participants